import base64
import urllib.parse
import requests

from .baidu_ocr_cnf import BaiduOCRConfig, with_config


@with_config(BaiduOCRConfig)
class BaiduOCR:
    def __init__(self):
        self.access_token = None
        self._get_access_token()

    def _get_access_token(self):
        """
        使用 AK，SK 生成鉴权签名（Access Token）
        """
        url = self.OAUTH_BASE_URL
        params = {
            "grant_type": "client_credentials",
            "client_id": self.API_KEY,
            "client_secret": self.SECRET_KEY,
        }
        try:
            response = requests.post(url, params=params)
            response.raise_for_status()  # 如果请求失败则抛出异常
            self.access_token = response.json().get("access_token")
            if not self.access_token:
                raise ValueError("获取 access_token 失败，请检查 API Key 和 Secret Key")
        except requests.exceptions.RequestException as e:
            print(f"请求 access_token 时发生网络错误: {e}")
            raise
        except ValueError as e:
            print(e)
            raise

    def recognize_text(
        self,
        image: str,
        is_path: bool = True,
        detect_direction: bool = False,
        paragraph: bool = False,
        probability: bool = False,
        multidirectional_recognize: bool = False,
    ) -> dict:
        """
        识别图片中的文字。

        Args:
            image (str): 图片的路径或Base64编码的字符串。
            is_path (bool): 指示'image'参数是文件路径还是Base64字符串。默认为True（文件路径）。
            detect_direction (bool): 是否检测图像朝向。默认为False。
            paragraph (bool): 是否输出段落信息。默认为False。
            probability (bool): 是否返回每个识别字符的置信度。默认为False。
            multidirectional_recognize (bool): 是否启用多方向文字识别。默认为False。

        Returns:
            dict: 包含识别结果的字典。
        """
        if not self.access_token:
            raise ConnectionError("Access Token 不可用，无法进行识别")

        url = f"{self.OCR_API_BASE_URL}/accurate_basic?access_token={self.access_token}"

        if is_path:
            image_base64 = self._get_file_content_as_base64(image, urlencoded=True)
        else:
            image_base64 = urllib.parse.quote_plus(image)

        payload = f"image={image_base64}"
        payload += f"&detect_direction={str(detect_direction).lower()}"
        payload += f"&paragraph={str(paragraph).lower()}"
        payload += f"&probability={str(probability).lower()}"
        payload += (
            f"&multidirectional_recognize={str(multidirectional_recognize).lower()}"
        )

        headers = {
            "Content-Type": "application/x-www-form-urlencoded",
            "Accept": "application/json",
        }

        try:
            response = requests.post(url, headers=headers, data=payload.encode("utf-8"))
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"请求OCR识别时发生网络错误: {e}")
            return {}

    def recognize_text_from_url(
        self,
        image_url: str,
        detect_direction: bool = False,
        paragraph: bool = False,
        probability: bool = False,
        multidirectional_recognize: bool = False,
    ) -> dict:
        """
        识别在线图片中的文字。

        Args:
            image_url (str): 图片的URL。
            detect_direction (bool): 是否检测图像朝向。默认为False。
            paragraph (bool): 是否输出段落信息。默认为False。
            probability (bool): 是否返回每个识别字符的置信度。默认为False。
            multidirectional_recognize (bool): 是否启用多方向文字识别。默认为False。

        Returns:
            dict: 包含识别结果的字典。
        """
        if not self.access_token:
            raise ConnectionError("Access Token 不可用，无法进行识别")

        url = f"{self.OCR_API_BASE_URL}/accurate_basic?access_token={self.access_token}"

        payload = f"url={urllib.parse.quote_plus(image_url)}"
        payload += f"&detect_direction={str(detect_direction).lower()}"
        payload += f"&paragraph={str(paragraph).lower()}"
        payload += f"&probability={str(probability).lower()}"
        payload += (
            f"&multidirectional_recognize={str(multidirectional_recognize).lower()}"
        )

        headers = {
            "Content-Type": "application/x-www-form-urlencoded",
            "Accept": "application/json",
        }

        try:
            response = requests.post(url, headers=headers, data=payload.encode("utf-8"))
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"请求OCR识别时发生网络错误: {e}")
            return {}

    @staticmethod
    def _get_file_content_as_base64(path: str, urlencoded: bool = False) -> str:
        """
        获取文件base64编码
        :param path: 文件路径
        :param urlencoded: 是否对结果进行urlencoded
        :return: base64编码信息
        """
        with open(path, "rb") as f:
            content = base64.b64encode(f.read()).decode("utf8")
            if urlencoded:
                content = urllib.parse.quote_plus(content)
        return content
